#include <cstdio>
#include <cmath>

#include <Element.d/Helm.d/Tetra10HelmGal.h>
#include <Math.d/FullSquareMatrix.h>
#include <Driver.d/Domain.h>
#include <Utils.d/dofset.h>
#include <Utils.d/linkfc.h>
extern bool useFull;

Tetra10HelmGal::Tetra10HelmGal(int* nodenums) { 

 int i;
 for(i=0;i<10;i++) nn[i] = nodenums[i];
}


Element * Tetra10HelmGal::clone() {

 return new Tetra10HelmGal(*this);
}


void Tetra10HelmGal::renum(int *table) {

 int i;
 for(i=0;i<10;i++) nn[i] = table[nn[i]];
}


void Tetra10HelmGal::renum(EleRenumMap& table) {

 int i;
 for(i=0;i<10;i++) nn[i] = table[nn[i]];
}


double Tetra10HelmGal::getMass(CoordSet& cs) {

 fprintf(stderr,"Tetra10HelmGal::getMass not implemented and should not be called.\n");
 return 0.0;
}


FullSquareMatrix Tetra10HelmGal::massMatrix(CoordSet &cs,double *mel,int cmflg) 
{
 FullSquareMatrix mass(10,mel);

 double dxdxi[15][3][3], det[15];
 computedxdxi(cs,15,tetra10_derivatives,dxdxi,det);

 int i,j,k,nint = 15;
 for(j=0;j<10;j++) for(k=j;k<10;k++) {
   mass[j][k] = 0.0;
   for(i=0;i<nint;i++) mass[j][k] += tetra10_weights[i]*tetra10_values[i][j]*
                                     tetra10_values[i][k]*det[i];
 }

 for(j=0;j<10;j++) for(k=0;k<j;k++) mass[j][k] = mass[k][j];

 mass /= getProperty()->rho; 
 return mass;
}


void Tetra10HelmGal::computedxdxi(CoordSet &cs, int nint, double (*derivatives)[10][3], Matrix33 *dxdxi, double *det) {

 int i,j,k;
 Node nd[10];
 for(i=0;i<10;i++) nd[i] = cs.getNode(nn[i]);

 double coord[10][3];
 for(i=0;i<10;i++) {
   coord[i][0] = nd[i].x;
   coord[i][1] = nd[i].y;
   coord[i][2] = nd[i].z;
 }

 for(j=0;j<3;j++) for(k=0;k<3;k++) {
   for(i=0;i<nint;i++) { 
     dxdxi[i][j][k] = 0.0;
     int m;
     for(m=0;m<10;m++) 
       dxdxi[i][j][k] += derivatives[i][m][k] * coord[m][j]; 
   }
 }

 for(i=0;i<nint;i++) {
   Matrix33 &x = dxdxi[i];
   det[i] = 
   -x[0][2]*x[1][1]*x[2][0] + x[0][1]*x[1][2]*x[2][0] + 
    x[0][2]*x[1][0]*x[2][1] - x[0][0]*x[1][2]*x[2][1] - 
    x[0][1]*x[1][0]*x[2][2] + x[0][0]*x[1][1]*x[2][2];
 }
 
}


FullSquareMatrix
Tetra10HelmGal::stiffness(CoordSet &cs, double *Ks, int flg )
{
 FullSquareMatrix stif(10,Ks);

 double dxdxi[15][3][3], det[15]; int nint = 15;
 computedxdxi(cs,nint,tetra10_derivatives,dxdxi,det);


 for(int j=0;j<10;j++) for(int k=0;k<10;k++) stif[j][k] = 0.0;

 for(int i=0;i<nint;i++) {
   Matrix33 &x = dxdxi[i];
   double inv[3][3];
   inv[0][0] = -x[1][2]*x[2][1] + x[1][1]*x[2][2];
   inv[0][1] = x[0][2]*x[2][1] - x[0][1]*x[2][2];
   inv[0][2] = -x[0][2]*x[1][1] + x[0][1]*x[1][2];
   inv[1][0] = x[1][2]*x[2][0] - x[1][0]*x[2][2];
   inv[1][1] = -x[0][2]*x[2][0] + x[0][0]*x[2][2];
   inv[1][2] = x[0][2]*x[1][0] - x[0][0]*x[1][2];
   inv[2][0] = -x[1][1]*x[2][0] + x[1][0]*x[2][1];
   inv[2][1] = x[0][1]*x[2][0] - x[0][0]*x[2][1];
   inv[2][2] = -x[0][1]*x[1][0] + x[0][0]*x[1][1];

   double grad[10][3];
   int l,m,n;
   for(l=0;l<10;l++) for(m=0;m<3;m++) {
     grad[l][m] = 0.0;
     for(n=0;n<3;n++) grad[l][m] += inv[n][m] * tetra10_derivatives[i][l][n];
   }

   for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<3;n++)
     stif[l][m] += tetra10_weights[i] * grad[l][n] * grad[m][n] / det[i];
 }

 stif /= getProperty()->rho; 
 return stif;
}


FullSquareMatrix Tetra10HelmGal::acousticm(CoordSet &cs, double *d) 
{
 FullSquareMatrix sm(10,d); 

 double stif[10][10], mass[10][10];

 double dxdxi[15][3][3], det[15];
 computedxdxi(cs,15,tetra10_derivatives,dxdxi,det);

 int i,j,k,nint = 15;
 for(j=0;j<10;j++) for(k=j;k<10;k++) {
   mass[j][k] = 0.0;
   for(i=0;i<nint;i++) mass[j][k] += tetra10_weights[i]*tetra10_values[i][j]*
                                     tetra10_values[i][k]*det[i];
 }

 for(j=0;j<10;j++) for(k=0;k<j;k++) mass[j][k] = mass[k][j];

 for(j=0;j<10;j++) for(k=0;k<10;k++) stif[j][k] = 0.0;

 for(i=0;i<nint;i++) {
   Matrix33 &x = dxdxi[i];
   double inv[3][3];
   inv[0][0] = -x[1][2]*x[2][1] + x[1][1]*x[2][2];
   inv[0][1] = x[0][2]*x[2][1] - x[0][1]*x[2][2];
   inv[0][2] = -x[0][2]*x[1][1] + x[0][1]*x[1][2];
   inv[1][0] = x[1][2]*x[2][0] - x[1][0]*x[2][2];
   inv[1][1] = -x[0][2]*x[2][0] + x[0][0]*x[2][2];
   inv[1][2] = x[0][2]*x[1][0] - x[0][0]*x[1][2];
   inv[2][0] = -x[1][1]*x[2][0] + x[1][0]*x[2][1];
   inv[2][1] = x[0][1]*x[2][0] - x[0][0]*x[2][1];
   inv[2][2] = -x[0][1]*x[1][0] + x[0][0]*x[1][1];

   double grad[10][3];
   int l,m,n; 
   for(l=0;l<10;l++) for(m=0;m<3;m++) {
     grad[l][m] = 0.0;
     for(n=0;n<3;n++) grad[l][m] += inv[n][m] * tetra10_derivatives[i][l][n];
   }
   
   for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<3;n++)
     stif[l][m] += tetra10_weights[i] * grad[l][n] * grad[m][n] / det[i]; 
 }
  
 double kappa = prop -> kappaHelm; 
 double kk = kappa * kappa;

 for (i=0;i<10;i++) 
   for (j=0;j<10;j++) sm[i][j] = stif[i][j] - kk*mass[i][j];

 sm /= getProperty()->rho; 
 return sm;
}


int Tetra10HelmGal::numNodes() {
  if(useFull)
    return 10;
  else
    return 4;
}


int* Tetra10HelmGal::nodes(int *p) {
  if(useFull)
    {
      if(p == 0) p = new int[10];
 
      int i;  
      for(i=0;i<10;i++) p[i] = nn[i];
      
      return p;
    }
  else
    {
       if(p == 0) p = new int[4];
 
       int i;  
       for(i=0;i<4;i++) p[i] = nn[i];
      
       return p;
    }
}


int Tetra10HelmGal::numDofs() {
 return 10;
}


int* Tetra10HelmGal::dofs(DofSetArray &dsa, int *p) {

 if(p == 0) p = new int[10];

 int i;
 for(i=0;i<10;i++) p[i] = dsa.locate(nn[i],DofSet::Helm);

 return p;
}


void Tetra10HelmGal::markDofs(DofSetArray &dsa) {

 int i;
 for(i=0;i<10;i++) dsa.mark(nn[i],DofSet::Helm);
}


void Tetra10HelmGal::addFaces(PolygonSet *pset) {

 pset->addTri(this,nn[0], nn[4], nn[7]);
 pset->addTri(this,nn[4], nn[8], nn[7]);
 pset->addTri(this,nn[4], nn[1], nn[8]);
 pset->addTri(this,nn[7], nn[8], nn[3]);

 pset->addTri(this,nn[1], nn[5], nn[8]);
 pset->addTri(this,nn[5], nn[9], nn[8]);
 pset->addTri(this,nn[5], nn[2], nn[9]);
 pset->addTri(this,nn[8], nn[9], nn[3]);

 pset->addTri(this,nn[0], nn[7], nn[6]);
 pset->addTri(this,nn[6], nn[7], nn[9]);
 pset->addTri(this,nn[6], nn[9], nn[2]);
 pset->addTri(this,nn[7], nn[3], nn[9]);

 pset->addTri(this,nn[0], nn[6], nn[4]);
 pset->addTri(this,nn[4], nn[6], nn[5]);
 pset->addTri(this,nn[4], nn[5], nn[1]);
 pset->addTri(this,nn[6], nn[2], nn[5]);
}


void Tetra10HelmGal::getNormalDeriv(CoordSet&cs,ComplexD *uel, int nsc,
                                         int *sc, ComplexD *grad) {

 int iVertex[3];
 int i;

 for(i=0;i<4;i++) {
    if (sc[0]==nn[i]) iVertex[0] = i;
    if (sc[1]==nn[i]) iVertex[1] = i;
    if (sc[2]==nn[i]) iVertex[2] = i;
 }

 if (iVertex[0] > iVertex[1]) { 
   int tmp = iVertex[0]; iVertex[0] = iVertex[1]; iVertex[1] = tmp;
 }
 if (iVertex[0] > iVertex[2]) { 
   int tmp = iVertex[0]; iVertex[0] = iVertex[2]; iVertex[2] = tmp;
 }
 if (iVertex[1] > iVertex[2]) { 
   int tmp = iVertex[1]; iVertex[1] = iVertex[2]; iVertex[2] = tmp;
 }

 double r,s,t;
 if ( (iVertex[0] == 0) && (iVertex[1] == 1) && (iVertex[2] == 2) ) {
    r=1.0/3.0; s = 1.0/3.0; t = 0.0;
 }
 else if ( (iVertex[0] == 0) && (iVertex[1] == 1) && (iVertex[2] == 3) ) {
    r=1.0/3.0; s = 0.0; t = 1.0/3.0;
 }
 else if ( (iVertex[0] == 0) && (iVertex[1] == 2) && (iVertex[2] == 3) ) {
    r=0.0; s = 1.0/3.0; t = 1.0/3.0;
 }
 else if ( (iVertex[0] == 1) && (iVertex[1] == 2) && (iVertex[2] == 3) ) {
    r=1.0/3.0; s = 1.0/3.0; t = 1.0/3.0;
 }
 else { 
   fprintf(stderr, "Error in Tetra10HelmGal::getNormalDeriv\n");
 }

 double dN[1][10][3];
 dN[0][0][0] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][0] = -1.0 + 4.0*r;
 dN[0][2][0] = 0.0;
 dN[0][3][0] = 0.0;
 dN[0][4][0] = -4.0*r + 4.0*(1.0 - r - s - t);
 dN[0][5][0] = 4.0*s;
 dN[0][6][0] = -4.0*s;
 dN[0][7][0] = -4.0*t;
 dN[0][8][0] = 4.0*t;
 dN[0][9][0] = 0.0;


 dN[0][0][1] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][1] = 0.0;
 dN[0][2][1] = -1.0 + 4.0*s;
 dN[0][3][1] = 0.0;
 dN[0][4][1] = -4.0*r;
 dN[0][5][1] = 4.0*r;
 dN[0][6][1] = -4.0*s + 4.0*(1.0 - r - s - t);
 dN[0][7][1] = -4.0*t;
 dN[0][8][1] = 0.0;
 dN[0][9][1] = 4.0*t;


 dN[0][0][2] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][2] = 0.0;
 dN[0][2][2] = 0.0;
 dN[0][3][2] = -1.0 + 4.0*t;
 dN[0][4][2] = -4.0*r;
 dN[0][5][2] = 0.0;
 dN[0][6][2] = -4.0*s;
 dN[0][7][2] = 4.0*(1.0 - r - s - t) - 4.0*t;
 dN[0][8][2] = 4.0*r;
 dN[0][9][2] = 4.0*s;

 double dxdxi[1][3][3], det[1];
 computedxdxi(cs,1,dN,dxdxi,det);
 Matrix33 &x = dxdxi[0];
 double inv[3][3];
 inv[0][0] = (-x[1][2]*x[2][1] + x[1][1]*x[2][2])/det[0];
 inv[0][1] = (x[0][2]*x[2][1] - x[0][1]*x[2][2])/det[0];
 inv[0][2] = (-x[0][2]*x[1][1] + x[0][1]*x[1][2])/det[0];
 inv[1][0] = (x[1][2]*x[2][0] - x[1][0]*x[2][2])/det[0];
 inv[1][1] = (-x[0][2]*x[2][0] + x[0][0]*x[2][2])/det[0];
 inv[1][2] = (x[0][2]*x[1][0] - x[0][0]*x[1][2])/det[0];
 inv[2][0] = (-x[1][1]*x[2][0] + x[1][0]*x[2][1])/det[0];
 inv[2][1] = (x[0][1]*x[2][0] - x[0][0]*x[2][1])/det[0];
 inv[2][2] = (-x[0][1]*x[1][0] + x[0][0]*x[1][1])/det[0];

 grad[0] = grad[1] = grad[2] = ComplexD(0.0,0.0);
 int l,m,n;
 for(l=0;l<10;l++) {
   for(m=0;m<3;m++) {
     for(n=0;n<3;n++)
       grad[m] += inv[n][m] * dN[0][l][n] * uel[l];
   }
 }
}



void Tetra10HelmGal::getNormalDeriv(CoordSet&cs,ComplexD *uel, int nsc,
                                  int *sc, ComplexD *grad, 
                                  double kappa, double *waveDir) {

 int iVertex[3];
 int i;

 for(i=0;i<4;i++) {
    if (sc[0]==nn[i]) iVertex[0] = i;
    if (sc[1]==nn[i]) iVertex[1] = i;
    if (sc[2]==nn[i]) iVertex[2] = i;
 }

 if (iVertex[0] > iVertex[1]) { 
   int tmp = iVertex[0]; iVertex[0] = iVertex[1]; iVertex[1] = tmp;
 }
 if (iVertex[0] > iVertex[2]) { 
   int tmp = iVertex[0]; iVertex[0] = iVertex[2]; iVertex[2] = tmp;
 }
 if (iVertex[1] > iVertex[2]) { 
   int tmp = iVertex[1]; iVertex[1] = iVertex[2]; iVertex[2] = tmp;
 }

 double r,s,t;
 if ( (iVertex[0] == 0) && (iVertex[1] == 1) && (iVertex[2] == 2) ) {
    r=1.0/3.0; s = 1.0/3.0; t = 0.0;
 }
 else if ( (iVertex[0] == 0) && (iVertex[1] == 1) && (iVertex[2] == 3) ) {
    r=1.0/3.0; s = 0.0; t = 1.0/3.0;
 }
 else if ( (iVertex[0] == 0) && (iVertex[1] == 2) && (iVertex[2] == 3) ) {
    r=0.0; s = 1.0/3.0; t = 1.0/3.0;
 }
 else if ( (iVertex[0] == 1) && (iVertex[1] == 2) && (iVertex[2] == 3) ) {
    r=1.0/3.0; s = 1.0/3.0; t = 1.0/3.0;
 }
 else { 
   fprintf(stderr, "Error in Tetra10HelmGal::getNormalDeriv\n");
 }

 double dN[1][10][3];
 dN[0][0][0] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][0] = -1.0 + 4.0*r;
 dN[0][2][0] = 0.0;
 dN[0][3][0] = 0.0;
 dN[0][4][0] = -4.0*r + 4.0*(1.0 - r - s - t);
 dN[0][5][0] = 4.0*s;
 dN[0][6][0] = -4.0*s;
 dN[0][7][0] = -4.0*t;
 dN[0][8][0] = 4.0*t;
 dN[0][9][0] = 0.0;


 dN[0][0][1] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][1] = 0.0;
 dN[0][2][1] = -1.0 + 4.0*s;
 dN[0][3][1] = 0.0;
 dN[0][4][1] = -4.0*r;
 dN[0][5][1] = 4.0*r;
 dN[0][6][1] = -4.0*s + 4.0*(1.0 - r - s - t);
 dN[0][7][1] = -4.0*t;
 dN[0][8][1] = 0.0;
 dN[0][9][1] = 4.0*t;


 dN[0][0][2] = 1.0 - 4.0*(1.0 - r - s - t);
 dN[0][1][2] = 0.0;
 dN[0][2][2] = 0.0;
 dN[0][3][2] = -1.0 + 4.0*t;
 dN[0][4][2] = -4.0*r;
 dN[0][5][2] = 0.0;
 dN[0][6][2] = -4.0*s;
 dN[0][7][2] = 4.0*(1.0 - r - s - t) - 4.0*t;
 dN[0][8][2] = 4.0*r;
 dN[0][9][2] = 4.0*s;

 double dxdxi[1][3][3], det[1];
 computedxdxi(cs,1,dN,dxdxi,det);
 Matrix33 &x = dxdxi[0];
 double inv[3][3];
 inv[0][0] = (-x[1][2]*x[2][1] + x[1][1]*x[2][2])/det[0];
 inv[0][1] = (x[0][2]*x[2][1] - x[0][1]*x[2][2])/det[0];
 inv[0][2] = (-x[0][2]*x[1][1] + x[0][1]*x[1][2])/det[0];
 inv[1][0] = (x[1][2]*x[2][0] - x[1][0]*x[2][2])/det[0];
 inv[1][1] = (-x[0][2]*x[2][0] + x[0][0]*x[2][2])/det[0];
 inv[1][2] = (x[0][2]*x[1][0] - x[0][0]*x[1][2])/det[0];
 inv[2][0] = (-x[1][1]*x[2][0] + x[1][0]*x[2][1])/det[0];
 inv[2][1] = (x[0][1]*x[2][0] - x[0][0]*x[2][1])/det[0];
 inv[2][2] = (-x[0][1]*x[1][0] + x[0][0]*x[1][1])/det[0];

 grad[0] = grad[1] = grad[2] = ComplexD(0.0,0.0);
 int l,m,n;
 for(l=0;l<10;l++) {
   for(m=0;m<3;m++) {
     for(n=0;n<3;n++)
       grad[m] += inv[n][m] * dN[0][l][n] * uel[l];
   }
 }

 double N[10];
 N[0] = (1.0-r-s-t)*(2.0*(1.0-r-s-t)-1.0);
 N[1] = r*(2.0*r-1.0);
 N[2] = s*(2.0*s-1.0);
 N[3] = t*(2.0*t-1.0);
 N[4] = 4.0*r*(1.0-r-s-t);
 N[5] = 4.0*r*s;
 N[6] = 4.0*s*(1.0-r-s-t);
 N[7] = 4.0*t*(1.0-r-s-t);
 N[8] = 4.0*r*t;
 N[9] = 4.0*s*t;

 Node nd[10];
 for(i=0;i<10;i++) nd[i] = cs.getNode(nn[i]);

 double coord[10][3];
 for(i=0;i<10;i++) {
   coord[i][0] = nd[i].x;
   coord[i][1] = nd[i].y;
   coord[i][2] = nd[i].z;
 }
 
 double point[3] = {0.0,0.0,0.0};
 for(m=0;m<3;m++) {
   for(l=0;l<10;l++) {
     point[m] += N[l]*coord[l][m];
   }
 }

 ComplexD tmp = exp(ComplexD(0.0,kappa)*
               (waveDir[0]*point[0]+waveDir[1]*point[1]+waveDir[2]*point[2]));
 for(m=0;m<3;m++) {
   grad[m] -= -ComplexD(0.0,1.0)*kappa*waveDir[m]*tmp; 
 }
}


double Tetra10HelmGal::tetra10_weights[15] = {
                   1.975308731198311e-02, 1.198951396316977e-02,
                   1.198951396316977e-02, 1.198951396316977e-02,
                   1.198951396316977e-02, 1.151136787104540e-02,
                   1.151136787104540e-02, 1.151136787104540e-02,
                   1.151136787104540e-02, 8.818342350423336e-03,
                   8.818342350423336e-03, 8.818342350423336e-03,
                   8.818342350423336e-03, 8.818342350423336e-03,
                   8.818342350423336e-03 };


double Tetra10HelmGal::tetra10_values [15][10] = { 
     {
  -0.125,  -0.125,  -0.125,  -0.125,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25
    },
    {
  0.32451652309273382,  -0.075053719656362886,  -0.075053719656362886,  -0.075053719656362886,  0.26638016183273128,  0.033834716792720293,  0.26638016183273128,  0.26638016183273128,  0.033834716792720293,  0.033834716792720293
    },
    {
  -0.075053719656362983,  0.3245165230927341,  -0.075053719656362886,  -0.075053719656362886,  0.26638016183273111,  0.26638016183273128,  0.033834716792720321,  0.033834716792720321,  0.26638016183273128,  0.033834716792720293
    },
    {
  -0.075053719656362719,  -0.075053719656362886,  0.3245165230927341,  -0.075053719656362886,  0.0338347167927203,  0.26638016183273128,  0.26638016183273078,  0.0338347167927203,  0.033834716792720293,  0.26638016183273128
    },
    {
  -0.075053719656362705,  -0.075053719656362886,  -0.075053719656362886,  0.3245165230927341,  0.033834716792720272,  0.033834716792720293,  0.033834716792720272,  0.26638016183273111,  0.26638016183273128,  0.26638016183273128
    },
    {
  -0.037319291258824133,  -0.115257699028758,  -0.115257699028758,  -0.115257699028758,  0.051958938513289588,  0.40907185760174331,  0.051958938513289588,  0.051958938513289588,  0.40907185760174331,  0.40907185760174331
    },
    {
  -0.115257699028758,  -0.037319291258823939,  -0.115257699028758,  -0.115257699028758,  0.051958938513289449,  0.051958938513289442,  0.40907185760174342,  0.40907185760174342,  0.051958938513289442,  0.40907185760174331
    },
    {
  -0.115257699028758,  -0.115257699028758,  -0.037319291258823939,  -0.115257699028758,  0.40907185760174342,  0.051958938513289442,  0.051958938513289449,  0.40907185760174342,  0.40907185760174331,  0.051958938513289442
    },
    {
  -0.115257699028758,  -0.115257699028758,  -0.115257699028758,  -0.037319291258823939,  0.40907185760174342,  0.40907185760174331,  0.40907185760174342,  0.051958938513289449,  0.051958938513289442,  0.051958938513289442
    },
    {
  -0.050000000000000037,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.01270166537925832,  0.099999999999999978,  0.099999999999999964,  0.099999999999999964,  0.099999999999999978,  0.78729833462074172
    },
    {
  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.10000000000000001,  0.01270166537925831,  0.10000000000000001,  0.78729833462074172,  0.099999999999999978,  0.099999999999999978
    },
    {
  -0.0500000000000001,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.7872983346207415,  0.099999999999999978,  0.099999999999999964,  0.099999999999999964,  0.099999999999999978,  0.01270166537925831
    },
    {
  -0.049999999999999878,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.099999999999999867,  0.78729833462074172,  0.099999999999999867,  0.012701665379258291,  0.099999999999999978,  0.099999999999999978
    },
    {
  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.099999999999999978,  0.099999999999999978,  0.01270166537925832,  0.099999999999999978,  0.78729833462074172,  0.099999999999999978
    },
    {
  -0.050000000000000037,  -0.049999999999999989,  -0.049999999999999989,  -0.049999999999999989,  0.099999999999999978,  0.099999999999999978,  0.78729833462074161,  0.099999999999999978,  0.01270166537925831,  0.099999999999999978
      }
   };

double Tetra10HelmGal::tetra10_derivatives[15][10][3] = { 
     {
       {
  0,  0,  0
        },
       {
  0,  0,  0
        },
       {
  0,  0,  0
        },
       {
  0,  0,  0
        },
       {
  0,  -1,  -1
        },
       {
  1,  1,  0
        },
       {
  -1,  0,  -1
        },
       {
  -1,  -1,  0
        },
       {
  1,  0,  1
        },
       {
  0,  1,  1
        }

    },
    {
       {
  -1.8963470633673201,  -1.8963470633673201,  -1.8963470633673201
        },
       {
  -0.63211568778910798,  0,  0
        },
       {
  0,  -0.63211568778910798,  0
        },
       {
  0,  0,  -0.63211568778910798
        },
       {
  2.5284627511564302,  -0.36788431221089202,  -0.36788431221089202
        },
       {
  0.36788431221089207,  0.36788431221089207,  0
        },
       {
  -0.36788431221089202,  2.5284627511564302,  -0.36788431221089202
        },
       {
  -0.36788431221089202,  -0.36788431221089202,  2.5284627511564302
        },
       {
  0.36788431221089207,  0,  0.36788431221089207
        },
       {
  0,  0.36788431221089207,  0.36788431221089207
        }

    },
    {
       {
  0.63211568778910765,  0.63211568778910765,  0.63211568778910765
        },
       {
  1.8963470633673201,  0,  0
        },
       {
  0,  -0.63211568778910798,  0
        },
       {
  0,  0,  -0.63211568778910798
        },
       {
  -2.5284627511564302,  -2.8963470633673198,  -2.8963470633673198
        },
       {
  0.36788431221089207,  2.8963470633673198,  0
        },
       {
  -0.36788431221089202,  0,  -0.36788431221089202
        },
       {
  -0.36788431221089202,  -0.36788431221089202,  0
        },
       {
  0.36788431221089207,  0,  2.8963470633673198
        },
       {
  0,  0.36788431221089207,  0.36788431221089207
        }

    },
    {
       {
  0.63211568778910787,  0.63211568778910787,  0.63211568778910787
        },
       {
  -0.63211568778910798,  0,  0
        },
       {
  0,  1.8963470633673201,  0
        },
       {
  0,  0,  -0.63211568778910798
        },
       {
  0,  -0.36788431221089202,  -0.36788431221089202
        },
       {
  2.8963470633673198,  0.36788431221089207,  0
        },
       {
  -2.8963470633673198,  -2.5284627511564302,  -2.8963470633673198
        },
       {
  -0.36788431221089202,  -0.36788431221089202,  0
        },
       {
  0.36788431221089207,  0,  0.36788431221089207
        },
       {
  0,  0.36788431221089207,  2.8963470633673198
        }

    },
    {
       {
  0.63211568778910809,  0.63211568778910809,  0.63211568778910809
        },
       {
  -0.63211568778910798,  0,  0
        },
       {
  0,  -0.63211568778910798,  0
        },
       {
  0,  0,  1.8963470633673201
        },
       {
  0,  -0.36788431221089202,  -0.36788431221089202
        },
       {
  0.36788431221089207,  0.36788431221089207,  0
        },
       {
  -0.36788431221089202,  0,  -0.36788431221089202
        },
       {
  -2.8963470633673198,  -2.8963470633673198,  -2.5284627511564302
        },
       {
  2.8963470633673198,  0,  0.36788431221089207
        },
       {
  0,  2.8963470633673198,  0.36788431221089207
        }

    },
    {
       {
  0.83752353395555867,  0.83752353395555867,  0.83752353395555867
        },
       {
  0.27917451131851961,  0,  0
        },
       {
  0,  0.27917451131851961,  0
        },
       {
  0,  0,  0.27917451131851961
        },
       {
  -1.11669804527408,  -1.27917451131852,  -1.27917451131852
        },
       {
  1.27917451131852,  1.27917451131852,  0
        },
       {
  -1.27917451131852,  -1.11669804527408,  -1.27917451131852
        },
       {
  -1.27917451131852,  -1.27917451131852,  -1.11669804527408
        },
       {
  1.27917451131852,  0,  1.27917451131852
        },
       {
  0,  1.27917451131852,  1.27917451131852
        }

    },
    {
       {
  -0.27917451131852,  -0.27917451131852,  -0.27917451131852
        },
       {
  -0.83752353395555901,  0,  0
        },
       {
  0,  0.27917451131851961,  0
        },
       {
  0,  0,  0.27917451131851961
        },
       {
  1.11669804527408,  -0.16247646604444099,  -0.16247646604444099
        },
       {
  1.27917451131852,  0.16247646604444091,  0
        },
       {
  -1.27917451131852,  0,  -1.27917451131852
        },
       {
  -1.27917451131852,  -1.27917451131852,  0
        },
       {
  1.27917451131852,  0,  0.16247646604444091
        },
       {
  0,  1.27917451131852,  1.27917451131852
        }

    },
    {
       {
  -0.27917451131852,  -0.27917451131852,  -0.27917451131852
        },
       {
  0.27917451131851961,  0,  0
        },
       {
  0,  -0.83752353395555901,  0
        },
       {
  0,  0,  0.27917451131851961
        },
       {
  0,  -1.27917451131852,  -1.27917451131852
        },
       {
  0.16247646604444091,  1.27917451131852,  0
        },
       {
  -0.16247646604444099,  1.11669804527408,  -0.16247646604444099
        },
       {
  -1.27917451131852,  -1.27917451131852,  0
        },
       {
  1.27917451131852,  0,  1.27917451131852
        },
       {
  0,  1.27917451131852,  0.16247646604444091
        }

    },
    {
       {
  -0.27917451131852,  -0.27917451131852,  -0.27917451131852
        },
       {
  0.27917451131851961,  0,  0
        },
       {
  0,  0.27917451131851961,  0
        },
       {
  0,  0,  -0.83752353395555901
        },
       {
  0,  -1.27917451131852,  -1.27917451131852
        },
       {
  1.27917451131852,  1.27917451131852,  0
        },
       {
  -1.27917451131852,  0,  -1.27917451131852
        },
       {
  -0.16247646604444099,  -0.16247646604444099,  1.11669804527408
        },
       {
  0.16247646604444091,  0,  1.27917451131852
        },
       {
  0,  0.16247646604444091,  1.27917451131852
        }

    },
    {
       {
  0.7745966692414834,  0.7745966692414834,  0.7745966692414834
        },
       {
  -0.77459666924148296,  0,  0
        },
       {
  0,  0.7745966692414834,  0
        },
       {
  0,  0,  0.7745966692414834
        },
       {
  0,  -0.22540333075851701,  -0.22540333075851701
        },
       {
  1.7745966692414801,  0.2254033307585166,  0
        },
       {
  -1.7745966692414801,  -1.5491933384829699,  -1.7745966692414801
        },
       {
  -1.7745966692414801,  -1.7745966692414801,  -1.5491933384829699
        },
       {
  1.7745966692414801,  0,  0.2254033307585166
        },
       {
  0,  1.7745966692414801,  1.7745966692414801
        }

    },
    {
       {
  -0.77459666924148296,  -0.77459666924148296,  -0.77459666924148296
        },
       {
  -0.77459666924148296,  0,  0
        },
       {
  0,  -0.77459666924148296,  0
        },
       {
  0,  0,  0.7745966692414834
        },
       {
  1.5491933384829699,  -0.22540333075851701,  -0.22540333075851701
        },
       {
  0.2254033307585166,  0.2254033307585166,  0
        },
       {
  -0.22540333075851701,  1.5491933384829699,  -0.22540333075851701
        },
       {
  -1.7745966692414801,  -1.7745966692414801,  0
        },
       {
  1.7745966692414801,  0,  0.2254033307585166
        },
       {
  0,  1.7745966692414801,  0.2254033307585166
        }

    },
    {
       {
  -0.77459666924148296,  -0.77459666924148296,  -0.77459666924148296
        },
       {
  0.7745966692414834,  0,  0
        },
       {
  0,  -0.77459666924148296,  0
        },
       {
  0,  0,  -0.77459666924148296
        },
       {
  0,  -1.7745966692414801,  -1.7745966692414801
        },
       {
  0.2254033307585166,  1.7745966692414801,  0
        },
       {
  -0.22540333075851701,  1.5491933384829699,  -0.22540333075851701
        },
       {
  -0.22540333075851701,  -0.22540333075851701,  1.5491933384829699
        },
       {
  0.2254033307585166,  0,  1.7745966692414801
        },
       {
  0,  0.2254033307585166,  0.2254033307585166
        }

    },
    {
       {
  0.7745966692414834,  0.7745966692414834,  0.7745966692414834
        },
       {
  0.7745966692414834,  0,  0
        },
       {
  0,  0.7745966692414834,  0
        },
       {
  0,  0,  -0.77459666924148296
        },
       {
  -1.5491933384829699,  -1.7745966692414801,  -1.7745966692414801
        },
       {
  1.7745966692414801,  1.7745966692414801,  0
        },
       {
  -1.7745966692414801,  -1.5491933384829699,  -1.7745966692414801
        },
       {
  -0.22540333075851701,  -0.22540333075851701,  0
        },
       {
  0.2254033307585166,  0,  1.7745966692414801
        },
       {
  0,  0.2254033307585166,  1.7745966692414801
        }

    },
    {
       {
  0.7745966692414834,  0.7745966692414834,  0.7745966692414834
        },
       {
  0.7745966692414834,  0,  0
        },
       {
  0,  -0.77459666924148296,  0
        },
       {
  0,  0,  0.7745966692414834
        },
       {
  -1.5491933384829699,  -1.7745966692414801,  -1.7745966692414801
        },
       {
  0.2254033307585166,  1.7745966692414801,  0
        },
       {
  -0.22540333075851701,  0,  -0.22540333075851701
        },
       {
  -1.7745966692414801,  -1.7745966692414801,  -1.5491933384829699
        },
       {
  1.7745966692414801,  0,  1.7745966692414801
        },
       {
  0,  1.7745966692414801,  0.2254033307585166
        }

    },
    {
       {
  -0.77459666924148296,  -0.77459666924148296,  -0.77459666924148296
        },
       {
  -0.77459666924148296,  0,  0
        },
       {
  0,  0.7745966692414834,  0
        },
       {
  0,  0,  -0.77459666924148296
        },
       {
  1.5491933384829699,  -0.22540333075851701,  -0.22540333075851701
        },
       {
  1.7745966692414801,  0.2254033307585166,  0
        },
       {
  -1.7745966692414801,  0,  -1.7745966692414801
        },
       {
  -0.22540333075851701,  -0.22540333075851701,  1.5491933384829699
        },
       {
  0.2254033307585166,  0,  0.2254033307585166
        },
       {
  0,  0.2254033307585166,  1.7745966692414801
        }

      }
   };


double Tetra10HelmGal::tetra10_vertex_derivatives[10][10][3] = 
{
{
{ -3.0000000000000000, -3.0000000000000000, -3.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ 4.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 4.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 4.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ 3.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ -4.0000000000000000, -4.0000000000000000, -4.0000000000000000},
{ 0.0000000000000000, 4.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 4.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 3.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 4.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ -4.0000000000000000, -4.0000000000000000, -4.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 4.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 3.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ -4.0000000000000000, -4.0000000000000000, -4.0000000000000000},
{ 4.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 4.0000000000000000, 0.0000000000000000}
},
{
{ -1.0000000000000000, -1.0000000000000000, -1.0000000000000000},
{ 1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ 0.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ 1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 2.0000000000000000, 2.0000000000000000, 0.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000}
},
{
{ -1.0000000000000000, -1.0000000000000000, -1.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, -1.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ -2.0000000000000000, 0.0000000000000000, -2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 2.0000000000000000}
},
{
{ -1.0000000000000000, -1.0000000000000000, -1.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 1.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, 0.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ 1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, -1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 1.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 2.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 0.0000000000000000}
},
{
{ 1.0000000000000000, 1.0000000000000000, 1.0000000000000000},
{ -1.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 1.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 1.0000000000000000},
{ 0.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ -2.0000000000000000, -2.0000000000000000, -2.0000000000000000},
{ 2.0000000000000000, 0.0000000000000000, 0.0000000000000000},
{ 0.0000000000000000, 2.0000000000000000, 2.0000000000000000}
}
};
